6f8c923df96d862851cde8e27e070f8b9542dd3e
[git-annex.git] /
1 [[!comment format=mdwn
2  username="joey"
3  subject="""comment 2"""
4  date="2020-05-04T17:30:59Z"
5  content="""
6 I took a look at this, the relevant code is here:
7
8                         warning "Resolving export conflict.."
9                         forM_ ts $ \oldtreesha -> do
10                                 -- Unexport both the srcsha and the dstsha,
11                                 -- because the wrong content may have
12                                 -- been renamed to the dstsha due to the
13                                 -- export conflict.
14                                 let unexportboth d =
15                                         [ Git.DiffTree.srcsha d
16                                         , Git.DiffTree.dstsha d
17                                         ]
18                                 -- Don't rename to temp, because the
19                                 -- content is unknown; delete instead.
20                                 mapdiff
21                                         (\diff -> commandAction $ startUnexport r db (Git.DiffTree.file diff) (unexportboth diff))
22                                         oldtreesha new
23
24 So, it diffs from the tree in the export conflict to the new, resolved tree.
25 Any file that differs -- eg, any file that was involved in the conflict -- 
26 gets removed from the export.
27
28 > In the todo, I said:
29
30 > For example, if A exports a tree containing `[foo]`, and B exports a tree
31 > containing `[foo, bar]`, bar gets unexported when resolving the conflict.
32
33 Let's be more clear about the content of the trees, and say A exports
34 `[(foo, 1)]` and B exports `[(foo, 1), (bar, 1)]`.
35
36 If the export is then resolved to `[(foo, 1), (bar, 1)]`,
37 we can see nothing needs to be done. But what it currently does is
38 diff from `[(foo, 1)]` to the resolution and so unexports bar.
39
40 If B had instead exported `[(foo, 1), (bar, 2)]`, then
41 it would still need to diff from that the the resolution, and so would
42 unexport bar, and so it should.
43
44 But.. but.. ugh. Consider an export conflict that started with `[(bar, 1)]`
45 exported. A exported `[(bar, 2)]` and B exported `[(baz, 1)]` (by renaming bar
46 to baz). So the export remote might contain `[(baz, 2)]` (A uploaded 2 to bar,
47 and then B renamed bar to baz) or it might contain `[(bar, 2), (baz, 1)]`;
48 we do not know ordering between A and B.
49
50 If the export conflict resolution is `[(bar, 2), (baz 1)]` then the tree
51 exported by B is a subset, so it skips that one. And the tree
52 exported by A is a subset, so ummm... it skips that one. And so nothing gets
53 unexported. Then, it proceeds to try to upload any missing files
54 to the export. If the export remote contains `[(bar, 2), (baz, 1)]` nothing is
55 missing, nothing gets uploaded, all is well. But if the export remote
56 contains `[(baz, 2)]`, it will upload `(bar, 2)`, resulting in 
57 `[(bar, 2), (baz 2)]`. That is not what it's supposed to contain.
58
59 So, no, this optimisation will not work!
60
61 The only way to make this optimisation work, I think, is to not do renaming
62 when updating export remotes. But file renaming is more common than export
63 conflicts; you can always adjust your workflow to avoid export conflicts,
64 by pulling from the remote you tend to conflict with, before performing an
65 export.
66 """]]